using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Timers;
using System.Xml;
using ViewOnCore.HostContract;

namespace ViewOn.AddInsHostContract.AutoUpdate
{
    sealed public class AutoUpdateService : IAutoUpdateService
    {

        #region Variables

        // API
        [DllImport("wininet.dll")]
        static private extern bool InternetGetConnectedState(out int Description, int ReservedValue);

        private Timer _timer = new Timer(4 * 60 * 1000); // every 4 hours

        //---- Settings
        private XmlDocument _xmlDocument;
        private XmlNode _autoUpdateNode;
        private XmlNode _autoUpdateViewOnModuleNode;

        #endregion

        #region Constructor

        public AutoUpdateService()
        {
            _timer.Elapsed += new ElapsedEventHandler(CheckVersion);
        }

        private void InitializeData()
        {
            if (_autoUpdateNode != null)
                return;

            string file = AppDomain.CurrentDomain.BaseDirectory + "ViewOn.exe.config";
            _xmlDocument = new XmlDocument();
            _xmlDocument.Load(file);

            _autoUpdateNode = _xmlDocument.SelectSingleNode("//configuration/ViewOn/autoupdate");

            _autoUpdateViewOnModuleNode = _xmlDocument.SelectSingleNode("//configuration/ViewOn/viewOnModules/viewOnModule[@name='ViewOn']");
        }

        #endregion

        #region Properties

        public bool IsConnected
        {
            get
            {
                int Desc;
                return InternetGetConnectedState(out Desc, 0);
            }
        }

        public int AutoUpdateEvery
        {
            get
            {
                InitializeData();

                return Int32.Parse(_autoUpdateNode.Attributes["every"].Value);
            }
            set
            {
                _autoUpdateNode.Attributes["every"].Value = value.ToString();

                try
                {
                    string file = AppDomain.CurrentDomain.BaseDirectory + "ViewOn.exe.config";
                    _xmlDocument.Save(file);
                }
                catch { }
            }
        }

        public bool CheckUpdateAtStartup
        {
            get
            {
                InitializeData();
                try
                {
                    return Boolean.Parse(_autoUpdateNode.Attributes["CheckUpdateAtStartup"].Value);
                }
                catch
                {
                    return true;
                }
            }
            set
            {
                try
                {
                    _autoUpdateNode.Attributes["CheckUpdateAtStartup"].Value = value.ToString();
                }
                catch
                {
                    XmlAttribute attribute = _xmlDocument.CreateAttribute("CheckUpdateAtStartup");
                    attribute.Value = value.ToString();
                    _autoUpdateNode.Attributes.Append(attribute);
                }

                try
                {
                    string file = AppDomain.CurrentDomain.BaseDirectory + "ViewOn.exe.config";
                    _xmlDocument.Save(file);
                }
                catch { }
            }
        }

        public DateTime LastCheckingDate
        {
            get
            {
                InitializeData();

                string lastChecking = _autoUpdateNode.Attributes["lastChecking"].Value;

                if (lastChecking.Length == 0)
                    return DateTime.MinValue;

                return DateTime.Parse(lastChecking);
            }
        }

        public DateTime NextCheckingDate
        {
            get
            {
                return LastCheckingDate.AddDays(AutoUpdateEvery);
            }
        }

        public Version Version
        {
            get
            {
                InitializeData();

                int major = Int32.Parse(_autoUpdateViewOnModuleNode.Attributes["majorVersion"].Value);
                int minor = Int32.Parse(_autoUpdateViewOnModuleNode.Attributes["minorVersion"].Value);

                return new Version(major, minor);
            }
        }

        #endregion

        #region Start Auto Update

        public bool StartAutoUpdateApplication()
        {
            //---- Update the file
            string file = AppDomain.CurrentDomain.BaseDirectory + "ViewOn.exe.config";
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(file);

            try
            {
                XmlNode autoUpdateNode = xmlDocument.SelectSingleNode("//configuration/ViewOn/autoupdate");
                autoUpdateNode.Attributes["lastChecking"].Value = DateTime.Today.ToShortDateString();
                xmlDocument.Save(file);
            }
            catch { }

            //----
            try
            {
                Process.Start("AutoUpdate.exe");
            }

            catch (Exception)
            {
                return false;
            }

            return true;
        }

        #endregion

        #region Check for the last version

        public void CheckVersion()
        {
            CheckVersion(null, null);
        }

        private void CheckVersion(object sender, ElapsedEventArgs e)
        {

            if (sender != null)
                _timer.Stop();

            //---- If we are not connected on the Internet
            if (!IsConnected)
            {
                // Recheck in 3 minutes.
                if (sender != null)
                    _timer.Start();
                return;
            }

            //--- Check in the XML file if we must start the auto-update
            if (LastCheckingDate == DateTime.MinValue)
            {
                StartAutoUpdateApplication();
                return;
            }

            if (DateTime.Today.CompareTo(NextCheckingDate) >= 0)
                StartAutoUpdateApplication();
        }

        #endregion

    }
}
